#ifndef __HEAD_H__
#define __HEAD_H__
// 头文件
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <stdbool.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <time.h>
#include <pwd.h>
#include <grp.h>
#include <dirent.h>
#include <sys/file.h>
#include <signal.h>
#include <pthread.h>
#include <semaphore.h>
#include <sys/wait.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/msg.h>
#include <sys/sem.h>
#include <stdarg.h>
// 头文件 网络编程
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/select.h>
#include <sys/epoll.h>
// 数据库
#include <sqlite3.h>
#define IP "192.168.70.15" // 服务器的 ip地址
#define POST 10086         // 服务器绑定的 端口号
#define MAX_FDS 1024       // epoll返回响应数组最大元素

time_t TIME_SERVER ;

// 数据库的指针
sqlite3 *db;

// 保存登录成功的 用户 和 商家 
 int fdArr[1000];                         //套接字数组
 char nameArr[1000][128];                    //名字数组
 int login_count  ;                           //登录的人数

// 客户端 当前的 用户账号
char currentLoginUserName[128];



// 保存客户端地址和套接字信息的结构体
typedef struct fd_addr_count
{
    int sockArr[MAX_FDS];                // 保存套接字的数组
    struct sockaddr_in addrArr[MAX_FDS]; // 保存地址的数组
    int count;
} FD_ADDR_COUNT;

enum msg_type
{
    _login,            // 登录类型的信息 用户
    _regist,           // 注册类型的信息 用户
    _pwdfind,          // 密码找回       用户
    _login_merchant,   // 登录类型的信息  商家
    _regist_merchant,  // 注册类型的信息  商家
    _pwdfind_merchant, // 密码找回       商家

    _yes, // 成功返回标志
    _no,  // 失败返回标志

    _view_products,       // 用户查看商品
    _buy_product,         // 用户购买商品
    _view_orders,         // 用户查看订单
    _cancel_order,        // 用户取消订单
    _review_product,      // 用户评价商品
    _view_reviews,        // 用户查看评价（指定商家和产品id）
    _return_goods,        // 用户退货
    _view_merchant_group, // 用户查看商家活动群
    _join_merchant_group, // 用户加入商家活动群
    _insert_merchant_group,//用户开始群聊 开始群聊 
    _consult_merchant,    // 用户咨询商家 和商家私聊 （商家并行 收 指定发）
    _view_personal_info,  // 用户查询个人信息
    _edit_personal_info,  // 用户编辑个人 信息
    _check_balance,       // 用户查看余额
    _tixian,              // 用户提现
    _withdraw_money,      // 用户修改密码
    _recharge_account,    // 用户充值账号

    _merchant_add_product,    // 商家添加商品
    _merchant_del_product,    // 商家删除商品
    _merchant_change_product, // 商家修改商品
    _merchant_find_product,   // 商家查询商品

    _msgChar, // 私聊 用户问 商家 问产品信息
    _allChar, // 群聊
    _kefu,    // 找客服

    singleChat,//用户间私聊
    groupChat,//在线的群聊

    _merchant_guke_chat,//商家私聊顾客

    _view_chat_noread,  //用户查看自己是不是 有 未读消息
    _view_chat_noread_shangjia,  //商家 查看自己是不是 有 未读消息

    _merchant_creat_group,      //商家创建群聊
    _merchant_insert_group,     //商家进入群聊

    over, // 发送数据结束标志

};




// 和客户端通讯的结构体
typedef struct msg
{
    enum msg_type type; // 发送的消息类型
    char data[MAX_FDS]; // 发送的消息字符串
} MSG;


typedef struct noread
{
    int siliao;         //未读的私聊消息
    int qunliao;        //未读的群聊消息
}NOREAD;


// 私聊 结构体
typedef struct single_Chat
{
     char self[64];//自己的名字
     char dest[64];//对方的名字
     char text[500];//聊天的内容
}SC;


//聊天表 评价 结构体
typedef struct char_char
{
    char   name[64];    //要聊天的对象 私聊对象 群聊对象 评论的对象
    char   data[512];   //聊天的数据保存区
    char   id[64];          //评价用的 id 索引
}CHAR;


typedef struct databaseret
{
    char **result; // 查询的结果是 一个字符串数组
    int row;       // 查询到的行
    int col;       // 查询到的列
} RET;


//聊天结构体 私聊 群聊
typedef struct chat
{
    char name[128];     
    //店铺名或者用户名  通过这两个找到对方的 fd 和 用户名绑定
    //在线就发送  fd在登录成功时更新到数据库 
    //不在线就发送到数据库中存起来 通过 登录成功保存的数组（套接字 和 用户名/商家店铺 ） 循环比较一下 
    char data[512];     //聊天的信息 （如果大于 就 判断 要 分多次 发送）

}CHAT;


// 登录  用的结构体
typedef struct lg
{
    char name[128]; // 用户名
    char pwd[128];  // 密码
    int flag;       // 用户权限标志
    char find[16];  // 用户找回信息检索 电话

} LOGIN;

// 注册用的 结构体
typedef struct rg
{
    char name[128]; // 用户名
    char pwd[128];  // 密码
    int flag;       // 用户权限标志   普通用户 0   商家 1  管理者 9999
    char find[16];  // 用户找回信息检索 电话
    int value;      // 用户余额
} REGIST;

// 商品 参数的 结构体
typedef struct product
{
    int  id;                  //商品id号
    char merchant_name[128]; // 商家名
    char product_name[128];  // 商品名
    int product_val;         // 商品价格
    int product_num;         // 商品数量

} PRODUCT;

// 修改商品专用 商品 参数的 结构体
typedef struct product_change
{
    char merchant_name[128];    // 商家名 老 （不会改变 索引用）
    char product_old_name[128]; // 商品名 老  （被修改前的索引）
    char product_new_name[128]; // 新商品名
    int product_val;            // 商品价格
    int product_num;            // 商品数量

} PRODUCT_CHANGE;

// 常用宏定义
#define FOPEN_ERR(FP)           \
    if (NULL == FP)             \
    {                           \
        perror("fopen error:"); \
        return -1;              \
    }

#define OPEN_ERR(FD)                                                    \
    if (EOF == FD)                                                      \
    {                                                                   \
        printf("文件:%s 函数:%s 行:%d\n" __FILE__, __func__, __LINE__); \
        perror("open error:");                                          \
        return -1;                                                      \
    }

#define OPEN_DIR_ERR(DIR)      \
    if (NULL == DIR)           \
    {                          \
        perror("open error:"); \
        return -1;             \
    }

// 标准错误
#define ERRLOG(STR)                                                                     \
    do                                                                                  \
    {                                                                                   \
        printf("%s 文件 %s 行 %d 错误:%s\n", STR, __FILE__, __LINE__, strerror(errno)); \
    } while (0);

#endif